package com.bifrost.service;

import com.bifrost.entity.Customer;
import com.bifrost.entity.CustomerType;
import com.bifrost.excel.model.CustomerInfo;
import com.bifrost.model.vo.PageVO;
import com.bifrost.repository.CustomerRepository;
import com.bifrost.repository.CustomerTypeRepository;
import com.bifrost.util.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import sun.util.calendar.LocalGregorianCalendar;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class CustomerInfoService {
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    private CustomerTypeRepository customerTypeRepository;
    /*
       积分条件查询conditionType
       1为 大于
       2为 大于等于
       3为 小于
       4为 小于等于
       5为 等于
    */
    public List<CustomerInfo> queryCustomerInfo(List<Long> storeIds, String phone, String cardNumber, String customerName, String[] registerDate, BigInteger bouns, Integer conditionType){
        Specification<Customer> specification = getSpecification(storeIds, phone, cardNumber, customerName, registerDate, bouns, conditionType,null);
        List<Customer> list = customerRepository.findAll(specification);
        return assembe(list);
    }

    private List<CustomerInfo> assembe(List<Customer> list){
        List<CustomerInfo> customerInfoList = new ArrayList<>();
        Integer index = 0;
        for (Customer customer:list
                ) {
            index++;
            CustomerInfo customerInfo = new CustomerInfo();
            customerInfo.setSerialNumber(index.toString());
            customerInfo.setCustomerId(customer.getCustomerId());
            customerInfo.setCardNumber(customer.getLoyaltyCard());
            customerInfo.setPhone(customer.getCustomerPhone());
            customerInfo.setCustomerName(customer.getCustomerLastname());
            customerInfo.setNickName(customer.getCustomerNickname());
            String gender = customer.getCustomerGender();
            if("1".equals(gender)){
                customerInfo.setGender("男");
            }else if("2".equals(gender)){
                customerInfo.setGender("女");
            }else {
                customerInfo.setGender("保密");
            }
            customerInfo.setRegisterDate(DateUtils.formatDate(customer.getCreatedTimestamp()));
            customerInfo.setBonus(customer.getBonusPoints());
            customerInfo.setIdCard(customer.getIdentificationId());
            customerInfo.setEmail(customer.getCustomerEmail());
            CustomerType type = customer.getCustomerType();
            customerInfo.setCustomerType(type==null?"":type.getName());
            customerInfo.setIsActive(customer.isActive()?"是":"否");
            customerInfoList.add(customerInfo);
        }
        return customerInfoList;
    }

    public PageVO pageCustomerInfo(List<Long> storeIds, String phone, String cardNumber, String customerName, String[] registerDate, BigInteger bouns, Integer conditionType, Integer page, Integer pageSize, Boolean isActive){
        Specification<Customer> specification = getSpecification(storeIds, phone, cardNumber, customerName, registerDate, bouns, conditionType,isActive);
        Pageable pageRequest = new PageRequest(page-1,pageSize);
        Page<Customer> customerPage = customerRepository.findAll(specification, pageRequest);
        List<CustomerInfo> infoList = assembe(customerPage.getContent());
        Long totalElements = customerPage.getTotalElements();
        return new PageVO(page, pageSize, totalElements.intValue(), infoList);
    }
    private Specification<Customer> getSpecification(List<Long> storeIds, String phone, String cardNumber, String customerName, String[] registerDate, BigInteger bouns, Integer conditionType,Boolean isActive){
        return new Specification<Customer>() {
            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.isNotNull(root.get("loyaltyCard")));
                if(CollectionUtils.isNotEmpty(storeIds)){
                    Path<Long> queryStoreId = root.get("merchantStore").get("merchantId");
                    predicates.add(queryStoreId.in(storeIds));
                }
                if(StringUtils.isNotBlank(phone)){
                    Path<String> queryPhone = root.get("customerPhone");
                    predicates.add(cb.equal(queryPhone,phone));
                }
                if(StringUtils.isNotBlank(cardNumber)){
                    Path<String> queryCardNumber = root.get("loyaltyCard");
                    predicates.add(cb.equal(queryCardNumber,cardNumber));
                }
                if(StringUtils.isNotBlank(customerName)){
                    Path<String> queryCustomerName = root.get("customerLastname");
                    predicates.add(cb.like(queryCustomerName,customerName));
                }
                if(registerDate[0]!=null&&registerDate[1]!=null){
                    Path<Date> queryCreateTime = root.get("createdTimestamp");
                    Date startDate = DateUtils.parse(registerDate[0], DateUtils.DEFAULT_DATE_FORMAT);
                    Date endDate = DateUtils.parse(registerDate[1], DateUtils.DEFAULT_DATE_FORMAT);
                    predicates.add(cb.between(queryCreateTime,startDate,endDate));
                }
                if(bouns!=null){
                    Path<BigInteger> queryBonus = root.get("bonusPoints");
                    if(1==conditionType){
                        predicates.add(cb.greaterThan(queryBonus,bouns));
                    }else if(2==conditionType){
                        predicates.add(cb.greaterThanOrEqualTo(queryBonus,bouns));
                    }else if(3==conditionType){
                        predicates.add(cb.lessThan(queryBonus,bouns));
                    }else if(4==conditionType){
                        predicates.add(cb.lessThanOrEqualTo(queryBonus,bouns));
                    }else if(5==conditionType){
                        predicates.add(cb.equal(queryBonus,bouns));
                    }
                }
                if (isActive!=null){
                    Path<Boolean> queryActive = root.get("isActive");
                    predicates.add(cb.equal(queryActive,isActive));
                }
                Predicate[] p = new Predicate[predicates.size()];
                return cb.and(predicates.toArray(p));
            }
        };
    }
}
